<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1" />
  <title>右键画画 — 纯静态绘图页面</title>
  <style>
    *{box-sizing:border-box;font-family:Inter,system-ui,Arial}
    html,body{height:100%;margin:0}
    .app{display:flex;height:100vh}
    /* 侧栏 */
    .sidebar{width:220px;padding:12px;background:#0f172a;color:#e6eef8;display:flex;flex-direction:column;gap:12px}
    .sidebar h2{margin:0 0 6px 0;font-size:16px}
    .palette{display:grid;grid-template-columns:repeat(5,1fr);gap:6px}
    .swatch{height:36px;border-radius:6px;cursor:pointer;border:2px solid rgba(255,255,255,0.08)}
    .controls{background:rgba(255,255,255,0.03);padding:8px;border-radius:8px}
    .row{display:flex;gap:8px;align-items:center}
    label{font-size:13px}
    .btn{padding:6px 8px;background:transparent;border:1px solid rgba(255,255,255,0.08);border-radius:6px;color:inherit;cursor:pointer}
    .btn:active{transform:translateY(1px)}
    .footer{margin-top:auto;font-size:12px;opacity:0.8}

    /* 画布区域 */
    .main{flex:1;display:flex;flex-direction:column}
    header.canvas-header{padding:8px 12px;background:#0b1220;color:#cfe8ff;display:flex;gap:12px;align-items:center}
    #canvas{flex:1;display:block;width:100%;height:calc(100vh - 56px);background:#fff;cursor:crosshair}

    /* 自定义右键菜单（选色/工具） */
    .menu{position:fixed;z-index:9999;background:#0b1220;color:#e6eef8;border:1px solid rgba(255,255,255,0.06);padding:8px;border-radius:8px;box-shadow:0 6px 20px rgba(2,6,23,0.6);display:none}
    .menu .menu-row{display:flex;gap:8px;margin-bottom:6px}
    .menu .menu-row:last-child{margin-bottom:0}
    .menu .tool{padding:6px 8px;border-radius:6px;background:transparent;border:1px solid rgba(255,255,255,0.05);cursor:pointer}

    /* 小提示 */
    .note{font-size:12px;color:#cbd5e1}
  </style>
</head>
<body>
  <div class="app">
    <aside class="sidebar">
      <h2>调色与工具（右键选择）</h2>
      <div class="controls" id="palette" title="在这里用右键选择颜色或工具">
        <div class="note">右键单击色块选择颜色；在空白处右键打开工具菜单。</div>
        <div style="height:8px"></div>
        <div class="palette" id="swatches"></div>
      </div>

      <div class="controls">
        <div class="row">
          <label for="sizeRange">画笔大小</label>
          <input id="sizeRange" type="range" min="1" max="80" value="6" style="flex:1">
        </div>
        <div class="row" style="margin-top:8px">
          <button class="btn" id="toolBrush">画笔</button>
          <button class="btn" id="toolEraser">橡皮</button>
          <button class="btn" id="undoBtn">撤销</button>
          <button class="btn" id="clearBtn">清空</button>
          <button class="btn" id="saveBtn">保存</button>
        </div>
        <div style="margin-top:8px" class="note">在画布上用右键按下并移动以绘画；左键也可绘制。</div>
      </div>

      <div class="footer">提示：我已禁用系统右键菜单仅在画布与选色区以便使用自定义交互。</div>
    </aside>

    <section class="main">
      <header class="canvas-header"><strong>右键绘画区</strong><span style="opacity:0.7"> — 右键按下并移动以绘制</span></header>
      <canvas id="canvas"></canvas>
    </section>
  </div>

  <!-- 自定义菜单：工具与颜色快速选择 -->
  <div id="contextMenu" class="menu" role="dialog" aria-hidden="true"></div>

  <script>
    // 基础元素
    const canvas = document.getElementById('canvas');
    const swatchesEl = document.getElementById('swatches');
    const paletteEl = document.getElementById('palette');
    const sizeRange = document.getElementById('sizeRange');
    const toolBrushBtn = document.getElementById('toolBrush');
    const toolEraserBtn = document.getElementById('toolEraser');
    const undoBtn = document.getElementById('undoBtn');
    const clearBtn = document.getElementById('clearBtn');
    const saveBtn = document.getElementById('saveBtn');
    const contextMenu = document.getElementById('contextMenu');

    // 画布大小自适应
    function resizeCanvas(){
      const dpr = window.devicePixelRatio || 1;
      canvas.width = Math.floor(canvas.clientWidth * dpr);
      canvas.height = Math.floor(canvas.clientHeight * dpr);
      ctx.setTransform(dpr,0,0,dpr,0,0);
      redrawFromHistory();
    }

    // 初始化 canvas 样式和上下文
    const ctx = canvas.getContext('2d', {alpha:true});
    canvas.style.width = '100%';
    canvas.style.height = '100%';

    // 预设颜色
    const colors = ['#000000','#444444','#8b5cf6','#06b6d4','#0ea5a4','#10b981','#84cc16','#f59e0b','#f97316','#ef4444','#ec4899','#7c3aed','#ffffff'];

    // 填充色块
    function buildSwatches(){
      swatchesEl.innerHTML = '';
      colors.forEach(c=>{
        const el = document.createElement('div');
        el.className = 'swatch';
        el.style.background = c;
        el.dataset.color = c;
        el.title = c;
        // 右键选择颜色
        el.addEventListener('contextmenu', e=>{
          e.preventDefault();
          setColor(c);
        });
        // 左键也可选择
        el.addEventListener('click', ()=> setColor(c));
        swatchesEl.appendChild(el);
      });
    }

    // 状态
    let tool = 'brush'; // 'brush' | 'eraser'
    let color = '#000';
    let size = Number(sizeRange.value);

    // 历史用于撤销（保存图像数据URL）
    const history = [];
    function pushHistory(){
      try{
        history.push(canvas.toDataURL());
        if(history.length>50) history.shift();
      }catch(e){console.warn('history push fail', e)}
    }
    function undo(){
      if(history.length===0) return clearCanvas();
      history.pop();
      const last = history[history.length-1];
      if(!last) { clearCanvas(); return }
      const img = new Image();
      img.onload = ()=>{
        ctx.clearRect(0,0,canvas.width,canvas.height);
        ctx.drawImage(img,0,0,canvas.width,canvas.height);
      };
      img.src = last;
    }

    function clearCanvas(){
      ctx.clearRect(0,0,canvas.width,canvas.height);
      pushHistory();
    }

    // 绘制逻辑
    let drawing = false;
    let last = {x:0,y:0};

    function setColor(c){ color = c; tool = 'brush'; updateUI(); }
    function setTool(t){ tool = t; updateUI(); }
    function setSize(s){ size = Number(s); updateUI(); }

    function updateUI(){
      toolBrushBtn.style.outline = tool==='brush' ? '2px solid rgba(255,255,255,0.12)' : 'none';
      toolEraserBtn.style.outline = tool==='eraser' ? '2px solid rgba(255,255,255,0.12)' : 'none';
      sizeRange.value = size;
    }

    // 坐标变换（相对于 canvas 元素）
    function getPos(e){
      const rect = canvas.getBoundingClientRect();
      const x = (e.clientX - rect.left);
      const y = (e.clientY - rect.top);
      return {x,y};
    }

    function beginDraw(e){
      drawing = true;
      last = getPos(e);
      ctx.lineJoin = ctx.lineCap = 'round';
      ctx.lineWidth = size;
      if(tool === 'eraser'){
        ctx.globalCompositeOperation = 'destination-out';
        ctx.strokeStyle = 'rgba(0,0,0,1)';
      } else {
        ctx.globalCompositeOperation = 'source-over';
        ctx.strokeStyle = color;
      }
      // push snapshot before drawing so undo returns to previous state
      pushHistory();
      // immediate small dot
      ctx.beginPath();
      ctx.moveTo(last.x, last.y);
      ctx.lineTo(last.x+0.1, last.y+0.1);
      ctx.stroke();
    }
    function drawMove(e){
      if(!drawing) return;
      const p = getPos(e);
      ctx.beginPath();
      ctx.moveTo(last.x, last.y);
      ctx.lineTo(p.x, p.y);
      ctx.stroke();
      last = p;
    }
    function endDraw(e){
      if(!drawing) return;
      drawing = false;
    }

    // 鼠标事件：支持右键绘制（button===2）和左键绘制（button===0）
    canvas.addEventListener('mousedown', (e)=>{
      // 仅在主绘图区域禁用默认右键菜单并使用右键绘制
      if(e.button===2 || e.button===0){
        e.preventDefault();
        beginDraw(e);
      }
    });
    window.addEventListener('mousemove', drawMove);
    window.addEventListener('mouseup', endDraw);

    // 防止浏览器默认右键菜单，仅在画布与调色区阻止以提供自定义交互
    canvas.addEventListener('contextmenu', e=>{ e.preventDefault(); /* don't show default */ });
    paletteEl.addEventListener('contextmenu', e=>{
      e.preventDefault();
      openPaletteMenu(e.clientX, e.clientY);
    });

    // 工具按钮
    toolBrushBtn.addEventListener('click', ()=> setTool('brush'));
    toolEraserBtn.addEventListener('click', ()=> setTool('eraser'));
    sizeRange.addEventListener('input', (e)=> setSize(e.target.value));
    undoBtn.addEventListener('click', undo);
    clearBtn.addEventListener('click', ()=>{ if(confirm('清空画布？')){ clearCanvas(); }});
    saveBtn.addEventListener('click', ()=>{
      const link = document.createElement('a');
      link.download = 'drawing.png';
      link.href = canvas.toDataURL('image/png');
      link.click();
    });

    // 自定义弹出菜单（在选色区空白处右键）
    function openPaletteMenu(x,y){
      contextMenu.innerHTML = '';
      // 颜色行
      const colorRow = document.createElement('div'); colorRow.className='menu-row';
      colors.slice(0,8).forEach(c=>{
        const b = document.createElement('button'); b.className='tool'; b.style.background=c; b.title=c; b.addEventListener('click', ()=>{ setColor(c); hideMenu(); });
        colorRow.appendChild(b);
      });
      contextMenu.appendChild(colorRow);
      // 工具行
      const toolsRow = document.createElement('div'); toolsRow.className='menu-row';
      ['brush','eraser'].forEach(t=>{
        const b = document.createElement('button'); b.className='tool'; b.textContent = t==='brush'? '画笔':'橡皮';
        b.addEventListener('click', ()=>{ setTool(t); hideMenu(); });
        toolsRow.appendChild(b);
      });
      // sizes
      const sizeRow = document.createElement('div'); sizeRow.className='menu-row';
      [4,8,16,32].forEach(s=>{
        const b = document.createElement('button'); b.className='tool'; b.textContent = s + 'px';
        b.addEventListener('click', ()=>{ setSize(s); hideMenu(); });
        sizeRow.appendChild(b);
      });
      contextMenu.appendChild(toolsRow);
      contextMenu.appendChild(sizeRow);

      // 显示位置
      contextMenu.style.left = x + 'px';
      contextMenu.style.top = y + 'px';
      contextMenu.style.display = 'block';
      contextMenu.setAttribute('aria-hidden','false');
      // 点击其它地方隐藏
      setTimeout(()=>{
        window.addEventListener('mousedown', outsideClick);
      },10);
    }
    function outsideClick(e){
      if(!contextMenu.contains(e.target)) hideMenu();
    }
    function hideMenu(){
      contextMenu.style.display = 'none';
      contextMenu.setAttribute('aria-hidden','true');
      window.removeEventListener('mousedown', outsideClick);
    }

    // 触摸兼容（触摸时当作左键绘制）
    canvas.addEventListener('touchstart', (e)=>{ e.preventDefault(); const t = e.touches[0]; beginDraw(t); }, {passive:false});
    canvas.addEventListener('touchmove', (e)=>{ const t = e.touches[0]; drawMove(t); }, {passive:false});
    canvas.addEventListener('touchend', endDraw);

    // 窗口尺寸调整
    window.addEventListener('resize', resizeCanvas);

    // 初始化
    buildSwatches();
    updateUI();
    // set canvas to fill available space
    // wait a tick to get layout
    setTimeout(()=>{
      // ensure canvas has size via CSS clientHeight
      canvas.style.width = '100%';
      canvas.style.height = '100%';
      resizeCanvas();
      // 初始空白历史
      pushHistory();
    },50);

    // 从 history 重绘（处理像素比）
    function redrawFromHistory(){
      if(history.length===0) return;
      const last = history[history.length-1];
      if(!last) return;
      const img = new Image();
      img.onload = ()=>{
        ctx.clearRect(0,0,canvas.width,canvas.height);
        ctx.drawImage(img,0,0,canvas.width,canvas.height);
      };
      img.src = last;
    }

    // 可选：键盘快捷键
    window.addEventListener('keydown', e=>{
      if(e.key==='e') setTool('eraser');
      if(e.key==='b') setTool('brush');
      if((e.ctrlKey||e.metaKey) && e.key==='z'){ e.preventDefault(); undo(); }
    });
  </script>
</body>
</html>
